package ExecuteEngine;

import java.util.*;
import parse.*;
import Const.Constant;
import Const.RC;

public class Sort extends Operation{
	public int order;
	public String attr;
	public Operation op;
	public int count = 0;
	public List<Tuple> result;
	public List<String> titles;
	
	public Sort(Orderby order, Operation o){
		this.order = order.order;
		this.attr = order.id;
		this.op = o;
		this.count = 0;
		this.result = new ArrayList<Tuple>();
		this.titles = new ArrayList<String>();
		this.type = Operation.SORT;
	}
	
	public RC.rc Open(){
		if(op.Open() != RC.rc.SUCCESS)
			return RC.rc.UNSUCCESS;
		
		
		Tuple src;
		int pos = 0;
		
		if(op.hasNext()){
			src = op.GetNext();
			
			for(int i=0; i<src.tuple.size(); i++){
				if(src.tuple.get(i).attrName.equals(this.attr)){
					pos = i;
					break;
				}
			}
		}
		else
			return RC.rc.UNSUCCESS;
		
		IntegerItem posItem = new IntegerItem(pos);
		Element posE = new Element(null, null, posItem);
		src.tuple.add(posE);
		result.add(src);
		
		while(op.hasNext()){
			src = op.GetNext();
			posItem = new IntegerItem(pos);
			posE = new Element(null, null, posItem);
			src.tuple.add(posE);
			result.add(src);
		}
		
		Collections.sort(result, new Comparator(){
			public int compare(Object t1, Object t2){
				Tuple c1 = (Tuple)t1;
				Tuple c2 = (Tuple)t2;
				
				int pos = ((IntegerItem)(c1.tuple.get(c1.tuple.size()-1).value)).value;
				
				if(c1.tuple.get(pos).value instanceof VarcharItem){
					String s1 = ((VarcharItem)c1.tuple.get(pos).value).value.toString();
					String s2 = ((VarcharItem)c2.tuple.get(pos).value).value.toString();
					
					return s1.compareTo(s2);
				}
				else{
					int n1 = ((IntegerItem)c1.tuple.get(pos).value).value;
					int n2 = ((IntegerItem)c2.tuple.get(pos).value).value;
					
					if(n1 == n2)
						return 0;
					else
					if(n1 > n2)
						return 1;
					else
						return -1;
				}
			}
		});
		
		for(int i=0; i<result.size(); i++)
			result.get(i).tuple.remove(result.get(i).tuple.size()-1);
		
		if(order == Orderby.DESC)
			count = result.size()-1;
		
		if(result.size() == 0)
			titles = op.GetTitles();
		else{
			Tuple t = result.get(0);
			
			for(int i=0; i<t.tuple.size(); i++){
				String attr = t.tuple.get(i).attrName;
			    titles.add(Tuple.Trim(attr));
			}
		}
		
		return RC.rc.SUCCESS;
	}
	
	public boolean hasNext(){
		if(order == Orderby.DESC){
			if(count >= 0)
				return true;
			else
				return false;
		}
		else{
			if(count < result.size())
				return true;
			else
				return false;
		}
	}
	
	public Tuple GetNext()
	{
		Tuple re =  result.get(count);
		
		if(order == Orderby.ASC)
			count++;
		else
			count--;
		
		return re;
	}
	
	public void Close(){
		op.Close();
	}
	
	public List<String> GetTitles(){
		return titles;
	}
}
